#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include"subsetsum.h"

typedef struct{

    unsigned int minVal;    // -范围 左闭右闭
    unsigned int maxVal;

    int * setA;     // -数组
    int setSize;    // -数组长度
    int keyValue;   // -要组成的值

    int solCount;   //  -解个数
}ThreadData;

#define THREAD_NUMBER 8


void * computeSubSet(void * arg){

    ThreadData * thdDataPtr = (ThreadData*)arg;
    for(unsigned int index = thdDataPtr->minVal;index <=  thdDataPtr->maxVal;index++){

        thdDataPtr->solCount += subsetnumEqual(thdDataPtr->setA,thdDataPtr->setSize,thdDataPtr->keyValue,index);
    }
    return NULL;
}

int main(int argc,char * argv[]){

    if(argc < 2){
        printf("need input data filename in command.\n");
        return EXIT_FAILURE;
    }
    // -according by input.txt get data
    FILE * fptr = fopen(argv[1],"r");
    if(NULL == fptr){

        printf("open file failed,filename = %s.\n",argv[1]);
        return EXIT_FAILURE;
    }
    int numInt = countInteger(fptr);

    fseek(fptr,0,SEEK_SET);
    int keyValue;
    if(fscanf(fptr,"%d\n",&keyValue)!=1){

        printf("fscanf error.\n");
        fclose(fptr);
        return EXIT_FAILURE;
    }
    numInt--;   // -去除keyValue
    int * array = malloc(sizeof(int) * numInt);
    // -临时变量-数组索引
    int index = 0;
    for(index = 0;index < numInt;index++){
        int aval;
        if(fscanf(fptr,"%d ",&aval)!=1){

            printf("fscanf error.\n");
            fclose(fptr);
            free(array);
            return EXIT_FAILURE;
        }
        array[index] = aval;
    }
    fclose(fptr);
    // -线程数据变量
    ThreadData thdData[THREAD_NUMBER];
    // -为每个线程分配相对应的计算量
    int countSize = countSubSetNumber(numInt) / THREAD_NUMBER;
    int minVal = 1;
    int maxVal = countSize;
    // -(（2^n）- 1 ）
    for(index = 0;index < THREAD_NUMBER - 1;index++){

        thdData[index].keyValue = keyValue;
        thdData[index].minVal = minVal;
        thdData[index].maxVal = maxVal;
        thdData[index].setA = array;
        thdData[index].solCount = 0;

        minVal = maxVal + 1;
        maxVal += countSize;
    }
    // -最后一个线程特殊处理
    thdData[THREAD_NUMBER-1].solCount = 0;
    thdData[THREAD_NUMBER-1].minVal = minVal;
    thdData[THREAD_NUMBER-1].maxVal = countSubSetNumber(numInt) - 1;
    thdData[THREAD_NUMBER-1].setA = array;
    thdData[THREAD_NUMBER-1].setSize = numInt;

    pthread_t thdInfo[THREAD_NUMBER];
    for(index = 0;index < THREAD_NUMBER;index++){

        int res;
        res = pthread_create(&thdInfo[index],NULL,computeSubSet,(void *)&thdData[index]);
        if(0 != res){

            printf("has error on pthread_create.\n");
            continue;
        }
    }
    // -等待线程结束
    int totalSolCount = 0;
    for(index = 0;index < THREAD_NUMBER;index++){

        totalSolCount += thdData[index].solCount;
        pthread_join(thdInfo[index],NULL);
    }
    printf("final solution = %d.\n",totalSolCount);
    return EXIT_SUCCESS;
}



